home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Games of Daze
/
Infomagic - Games of Daze (Summer 1995) (Disc 1 of 2).iso
/
x2ftp
/
msdos
/
docs
/
tut6new
/
tut6.cpp
< prev
next >
Wrap
C/C++ Source or Header
|
1995-01-04
|
14KB
|
387 lines
/////////////////////////////////////////////////////////////////////////////
// //
// TUTPROG6.CPP - VGA Trainer Program 6 (in Turbo C++ 3.0) //
// //
// "The VGA Trainer Program" is written by Denthor of Asphyxia. However it //
// was limited to Pascal only in its first run. All I have done is taken //
// his original release, translated it to C++ and touched up a few things. //
// I take absolutely no credit for the concepts presented in this code and //
// am NOT the person to ask for help if you are having trouble. //
// //
// Program Notes : This program demonstrates the advantages of //
// pregenerated arrays. //
// //
// The Compact memory model (-mc) seems to provide the //
// best results for this tutorial. Remember, use this //
// memory model when you have little code and lots of //
// data. //
// //
// Author : Grant Smith (Denthor) - denthor@beastie.cs.und.ac.za //
// Translator : Christopher G. Mann - r3cgm@dax.cc.uakron.edu //
// //
// Last Modified : January 4, 1995 //
// //
/////////////////////////////////////////////////////////////////////////////
// //
// INCLUDE FILES //
// //
#include <conio.h>
// clrscr(), getch(), kbhit(), gotoxy(),
// directvideo
#include <dos.h>
// MK_FP, geninterrupt()
#include <iostream.h>
// cout, memset(), memmove()
#include <math.h>
// sin(), cos()
#include <stdlib.h>
// calloc(), free(), exit()
// //
// CONSTANTS //
// //
const PI = 3.1415927;
const TABLESIZE = 900;
// //
// FUNCTION PROTOTYPES //
// //
// UTILITY FUNCTIONS
void SetMCGA();
void SetText();
void Cls(unsigned char Col);
void Pal(unsigned char ColorNo, unsigned char R,
unsigned char G, unsigned char B);
void Putpixel(int x, int y, unsigned char Col);
void WaitRetrace();
float rad(float theta);
// MID-LEVEL FUNCTIONS
void NormCirc();
void LookupCirc();
void PalPlay();
// //
// GLOBAL VARIABLE DECLARATIONS //
// //
// pointer to the offset of the VGA memory
unsigned char *vga = (unsigned char *) MK_FP(0xA000, 0);
// This is our temporary pallette. We only use colors 1 to 20, so we
// only have variables for those ones.
unsigned char Pall[18][3];
///////////////////////////////////////////////////////////////////////////////
// //
// MAIN FUNCTION //
// //
///////////////////////////////////////////////////////////////////////////////
void main() {
int loop1;
clrscr();
cout
<< "Hi there! This program will demonstrate the usefullness of\n"
<< "pregenerated arrays, also known as lookup tables. The program\n"
<< "will first draw a spiral without using a lookup table, rotate\n"
<< "the pallette until a key is pressed, the calculate the lookup\n"
<< "table, then draw the same spiral using the lookup table.\n\n";
cout
<< "This is merely one example for the wide range of uses of a\n"
<< "lookup table.\n\n";
cout
<< "Hit any key to contine ...";
getch();
SetMCGA();
// This handy trick allows you to use gotoxy() and cout in graphics mode.
directvideo = 0;
// This sets our pallette colors 0 to 17 with red values between 12 to 63.
for (loop1=0;loop1<18;loop1++) {
Pall[loop1][0] = ((loop1+1)*3)+9;
Pall[loop1][1] = 0;
Pall[loop1][2] = 0;
}
WaitRetrace();
// This sets the true pallette to variable Pall
for (loop1=0;loop1<18;loop1++)
// loop+1 (make sure to leave color 0 for black)
Pal(loop1+1,Pall[loop1][0],Pall[loop1][1],Pall[loop1][2]);
// This draws a spiral without lookups
NormCirc();
while (!kbhit()) PalPlay();
getch(); // clear the keyboard buffer after kbhit()
// This draws a spiral with lookups
LookupCirc();
while (!kbhit()) PalPlay();
getch();
getch();
SetText();
cout
<< "All done. This concludes the sixth sample program in the ASPHYXIA\n"
<< "Training series. You may reach DENTHOR under the name of GRANT\n"
<< "SMITH on the MailBox BBS, or leave a message to ASPHYXIA on the\n"
<< "ASPHYXIA BBS. I am also an avid Connectix BBS user.\n"
<< "Get the numbers from Roblist, or write to :\n"
<< " Grant Smith\n"
<< " P.O. Box 270\n"
<< " Kloof\n"
<< " 3640\n"
<< "I hope to hear from you soon!\n\n";
cout
<< "Hit any key to exit ...";
getch();
}
/////////////////////////////////////////////////////////////////////////////
// //
// SetMCGA() - This function gets you into 320x200x256 mode. //
// //
/////////////////////////////////////////////////////////////////////////////
void SetMCGA() {
_AX = 0x0013;
geninterrupt (0x10);
}
/////////////////////////////////////////////////////////////////////////////
// //
// SetText() - This function gets you into text mode. //
// //
/////////////////////////////////////////////////////////////////////////////
void SetText() {
_AX = 0x0003;
geninterrupt (0x10);
}
/////////////////////////////////////////////////////////////////////////////
// //
// Cls() - This clears the screen to the specified color. //
// //
/////////////////////////////////////////////////////////////////////////////
void Cls(unsigned char Col) {
memset(vga, Col, 0xffff);
}
/////////////////////////////////////////////////////////////////////////////
// //
// Pal() - This sets the Red, Green, and Blue values of a certain color. //
// //
/////////////////////////////////////////////////////////////////////////////
void Pal(unsigned char ColorNo, unsigned char R,
unsigned char G, unsigned char B) {
outp (0x03C8,ColorNo); // here is the pallette color I want to set
outp (0x03C9,R);
outp (0x03C9,G);
outp (0x03C9,B);
}
/////////////////////////////////////////////////////////////////////////////
// //
// Putpixel() - This puts a pixel at X,Y using color Col, on VGA or the //
// Virtual Screen; //
// //
/////////////////////////////////////////////////////////////////////////////
void Putpixel (int x, int y, unsigned char Col) {
memset(vga+x+(y*320),Col,1);
}
/////////////////////////////////////////////////////////////////////////////
// //
// WaitRetrace() - This waits until you are in a Verticle Retrace. //
// //
/////////////////////////////////////////////////////////////////////////////
void WaitRetrace() {
_DX = 0x03DA;
l1: asm {
in al,dx;
and al,0x08;
jnz l1;
}
l2: asm {
in al,dx;
and al,0x08;
jz l2;
}
}
/////////////////////////////////////////////////////////////////////////////
// //
// rad() - This calculates the degrees of an angle. //
// //
/////////////////////////////////////////////////////////////////////////////
float rad(float theta) {
return ((theta * PI)/180);
}
/////////////////////////////////////////////////////////////////////////////
// //
// NormCirc() - This generates a spiral without using a lookup table. //
// //
/////////////////////////////////////////////////////////////////////////////
void NormCirc() {
int loop1,x,y;
float deg,radius;
gotoxy(1,1);
cout << "Without pregenerated arrays.";
for (loop1=60;loop1>42;loop1--) {
deg = 0.0;
radius = (float) loop1;
do {
x = radius*cos(rad(deg));
y = radius*sin(rad(deg));
Putpixel(x+160,y+100,61-loop1);
deg += 0.4; // Increase the degree so the circle is round
radius -= 0.019; // Decrease the radius for a spiral effect
// NOTE: If you change this last statement to "radius -= 0.02;" like
// the Pascal code has it, you will get holes in the spiral. You
// get bonus credit if you can tell me why this is.
}
while (radius >= 0.0); // continue until the radius is zero (at center)
}
}
/////////////////////////////////////////////////////////////////////////////
// //
// LookupCirc() - This draws a spiral using a lookup table. //
// //
/////////////////////////////////////////////////////////////////////////////
void LookupCirc() {
int x, y, pos, loop1;
float radius, deg;
float *costbl=NULL, *sintbl=NULL;
// allocate memory for the two tables
costbl = (float *) calloc(TABLESIZE,sizeof(float));
sintbl = (float *) calloc(TABLESIZE,sizeof(float));
// always check to see if enough memory was allocated
if ((costbl == NULL) || (sintbl == NULL)) {
SetText();
cout << "Insufficient memory for lookup tables, exiting...";
exit(1);
}
Cls(0);
gotoxy(1,1);
cout << "Generating variables....";
// There are 360 degrees in a circle. If you increase the degrees by 0.4,
// the number of needed parts of the table is 360/0.4=900. (TABLESIZE)
//
// For greater accuracy I increase the degrees by 0.4, because if I
// increase them by one, holes are left in the final product as a
// result of the rounding error margin. This means the pregenerated array
// is bigger, takes up more memory and is slower to calculate, but
// the finished product looks better.
deg = 0.0;
for (loop1=0;loop1<TABLESIZE;loop1++) {
costbl[loop1] = cos(rad(deg));
sintbl[loop1] = sin(rad(deg));
deg += 0.4;
}
gotoxy(1,1);
cout << "With pregenerated arrays.";
// NOTE: The spiral drawn with this function leaves a small piece missing
// on the right side. It looks like a pie with a piece cut out. You get
// extra credit if you can tell me why this is.
for (loop1=60;loop1>42;loop1--) {
pos = 0;
radius = loop1;
do {
// Note how I am not recalculating sin and cos for each point.
x = radius*costbl[pos];
y = radius*sintbl[pos];
Putpixel(x+160,y+100,61-loop1);
// Decrease the radius for a spiral effect
radius -= 0.020;
// I only made a table from 1 to 900, so it must never exceed that,
// or the program will probably crash. Go ahead and increment
// pos while you are at it (more compact but less readable). :)
if (++pos > TABLESIZE-1) pos = 0;
}
while (radius >= 0.0);
}
// Freeing the memory taken up by the tables. This is very important.
free(costbl);
free(sintbl);
}
/////////////////////////////////////////////////////////////////////////////
// //
// PalPlay() - This function mucks about with our "virtual pallette", then //
// shoves it to the screen. //
// //
/////////////////////////////////////////////////////////////////////////////
void PalPlay() {
// This is used as a "temporary color" in our pallette
unsigned char Tmp[3];
int loop1;
// This copies color 0 from our virtual pallette to the Tmp variable.
memmove(Tmp,Pall[0],3);
// This moves the entire virtual pallette down one color.
memmove(Pall[0],Pall[1],17*3);
// This copies the Tmp variable to the bottom of the virtual pallette.
// Don't change 0: leave this always black to not change overscan color.
memmove(Pall[17],Tmp,3);
WaitRetrace();
for (loop1=0;loop1<18;loop1++)
Pal(loop1+1,Pall[loop1][0], Pall[loop1][1], Pall[loop1][2]);
}